package com.jie.crm.provider;

import java.beans.Introspector;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Entity;
import javax.persistence.Id;

import net.oschina.j2cache.CacheException;
import net.oschina.j2cache.CacheObject;

import org.springframework.data.jpa.repository.CommonJpaRepository;
import org.springframework.util.ClassUtils;

import spring.data.jpa.tools.DBHelper;
import spring.data.jpa.tools.Reflections;
import spring.data.jpa.tools.SpringContextHolder;

import com.jie.cache.provider.CacheProvider;
import com.jie.cache.support.CacheDef;

public class ObjectCacheProvider extends CacheProvider {

	public ObjectCacheProvider(CacheDef def) {
		super(def);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> getList() {
		Class<?> clazz = def.getClassName();
		Entity entity = clazz.getDeclaredAnnotation(Entity.class);
		if (null == entity) {
			throw new CacheException(def.getClassName() + "不是实体类");
		}
		CacheObject cache = j2cache.get("default", clazz.getName());
		if (cache.getValue() != null) {
			return (List<T>) cache.getValue();
		}
		String repoName = Introspector.decapitalize(ClassUtils.getShortName(clazz) + "Repository");
		CommonJpaRepository<?, ?> repository = SpringContextHolder.getBean(repoName);
		List<?> objects = DBHelper.bind(repository).findAll();
		j2cache.set("default", clazz.getName(), objects);
		return (List<T>) objects;
	}

	@Override
	public <T> Map<String, T> getMap() {
		List<T> list = getList();
		Map<String, T> resultMap = new HashMap<>();
		for (T t : list) {
			Field field = getIdField(t);
			if (field == null) {
				continue;
			}
			String key = String.valueOf(Reflections.getFieldValue(t, field.getName()));
			resultMap.put(key, t);
		}
		return resultMap;
	}

	public Field getIdField(Object t) {
		Field[] fields = t.getClass().getDeclaredFields();
		for (Field field : fields) {
			Id id = field.getAnnotation(Id.class);
			if (id == null) {
				continue;
			}
			return field;
		}
		return null;
	}
}
